/**
 * 分页组件
 *
 * @param id 翻页按钮组容器ID，此为组件内自动创建的一个DIV，需要与对应的CSS样式表中的ID一一对应
 * @param pageTotals 总页数
 * @param initItemNum 显示的翻页按钮（页号按钮）数量
 * @param space 前后待选页号按钮个数 </p>
 *              此数字必须小于initItemNum </p>
 *              为auto字符串则将根据initItemNum值计算前后待选个数，取平均值，满足前多后少 </p>
 *              为类似“6#5”的字符串则表示前待选量为6，后待选量为5 </p>
 *              为数字字符串则与此值为纯数字的意义相同 </p>
 * @param callback 翻页回调
 * @constructor
 */
function PageNav(id, pageTotals, initItemNum, space, callback) {
    if(!id) {
        this.id = "page_nav";
    } else {
        this.id = "" + id;
    }
    this.pageTotals = pageTotals;   //总页数
    this.initItemNum = initItemNum; //显示的页号按钮数量
    this.currPageIndex = -1;  //选中的页号，int
    this.$selectedItem = null;  //选中的按钮项
    this.callback = callback;
    this.leftSpace = 0;
    this.rightSpace = 0;
    this.isString = function(obj) {
        return Object.prototype.toString.call(obj) == "[object String]";
    };
    this.isNumber = function(obj) {
        return Object.prototype.toString.call(obj) == "[object Number]";
    };
    this.isNumeric = function(str) {
        if(this.isNumber(str)) return true;
        if(!this.isString(str)) return false;
        var reg = /^[0-9]+.?[0-9]*$/;
        if (reg.test(str)) {
            return true;
        }
        return false;
    };
    this.fixedSpace = function(space, _this) {
        if(_this.pageTotals <= _this.initItemNum) {
            _this.initItemNum = _this.pageTotals;
            _this.leftSpace = 0;
            _this.rightSpace = 0;
        } else {
            if(_this.isString(space)) {
                if(space == "auto") {
                    _this.rightSpace = Math.floor(_this.initItemNum / 2);
                    _this.leftSpace = _this.initItemNum - _this.rightSpace;
                } else if(space.indexOf("#")) {
                    var arr = space.split("#");
                    if(arr.length == 1) {
                        var v = parseInt(arr[0]);
                        _this.rightSpace = v;
                        _this.leftSpace = v;
                    } else if(arr.length > 1) {
                        _this.leftSpace = parseInt(arr[0]);
                        _this.rightSpace = parseInt(arr[1]);
                    }
                }
            } else if(_this.isNumber(space)) {
                if(space <= 0) {
                    _this.rightSpace = 1;
                    _this.leftSpace = 1;
                } else {
                    _this.rightSpace = space;
                    _this.leftSpace = space;
                }
            }
        }
    };
    this.fixedSpace(space, this);
    this.onClickHandler = function(evt) {
        var _this = evt.data;
        var $item = $(evt.currentTarget);
        var num_text = $item.text().trim();
        if(_this.isNumeric(num_text)) {
            var v = parseInt(num_text);
            _this.select(v);
        } else {
            var cls = $item.attr("class");
            if(cls == "page_prev") {
                _this.prev();
            } else if(cls == "page_next") {
                _this.next();
            } else if(cls == "page_first") {
                _this.first();
            } else if(cls == "page_last") {
                _this.last();
            }
        }
    };
    var html = '<div id="' + this.id + '">';
    html += '<span class="page_first">首页</span>';
    html += '<span class="page_prev">上一页</span>';
    for(var i = 0; i < this.initItemNum; i++) {
        html += '<span class="page_num">' + (i + 1) + '</span>';
    }
    html += '<span class="page_next">下一页</span>';
    html += '<span class="page_last">尾页(' + this.pageTotals + ')</span>';
    html += '</div>';
    var $pageNav = $(html);
    var cs = $pageNav.children("span");
    for(var i = 0; i < cs.length; i++) {
        var c = cs[i];
        $(c).on("click", null, this, this.onClickHandler);
    }
    this.navObj = $pageNav;
}

/**
 * 获取翻页导航的jQuery包装后的HTMLElement对象
 * @returns {JQuery<TElement extends Node> | jQuery | HTMLElement | *}
 */
PageNav.prototype.$object = function() {
    return this.navObj;
};

/**
 * 释放对象资源
 */
PageNav.prototype.dispose = function() {
    if(this.navObj) {
        var cs = this.navObj.children("span");
        for(var i = 0; i < cs.length; i++) {
            var c = cs[i];
            $(c).off("click", this.onClickHandler);
        }
        this.navObj.remove();
        this.navObj = null;
    }
    this.callback = null;
};

/**
 * 设置总页数
 *
 * @param value
 * @param itemNum 显示的页号项数量
 * @param space 前后待选页号按钮个数</p>
 *              此数字必须小于itemNum </p>
 *              为auto字符串则将根据initItemNum值计算前后待选个数，取平均值，满足前多后少 </p>
 *              为类似“6#5”的字符串则表示前待选量为6，后待选量为5 </p>
 *              为数字字符串则与此值为纯数字的意义相同 </p>
 */
PageNav.prototype.set = function(pageTotals, itemNum, space) {
    if(this.pageTotals == pageTotals && this.initItemNum == itemNum) return;
    if(!itemNum || itemNum <= 0) {
        itemNum = this.initItemNum;
    }
    var cs = this.navObj.children();
    var $page_last; //尾页按钮
    var $itemLast;  //最后一个页号翻页按钮
    var itemLastIdx; //最后一个页号按钮的位置索引
    for(var i = cs.length - 1; i >= 0; i--) {
        var $item = $(cs[i]);
        var cls = $item.attr("class");
        if(cls.indexOf("page_last") >= 0) {
            if(!$page_last) {
                $page_last = $item; //尾页肯定在最后一个翻页按钮的后面，故而不需要break
            }
        } else if(cls.indexOf("page_num") >= 0) {
            if(!$itemLast) {
                $itemLast = $item;
                itemLastIdx = i;
                break;
            }
        }
    }
    if(!$page_last) return;
    var text = $page_last.text();
    var txt = text.replace(/\([1-9][0-9]*\)/i, "(" + pageTotals + ")");
    $page_last.text(txt);
    this.pageTotals = pageTotals;
    var nowItemCount = this.initItemNum; //现有页号翻页按钮的数量
    this.initItemNum = itemNum;
    this.fixedSpace(space, this);
    if(nowItemCount > itemNum) {   //现有页号按钮多于指定需要显示的页号按钮数量，则需要删除相应数量的翻页按钮
        var offset = nowItemCount - itemNum;   //现有翻页按钮数量与指定数量的差量，需要删除的量
        var arr = [];
        for(var i = cs.length - 1; i >= 0; i--) {
            var $item = $(cs[i]);
            var cls = $item.attr("class");
            if(cls.indexOf("page_num") < 0) continue;
            arr.push($item);
            if(arr.length >= offset) break;
        }
        var isDel = false;  //是否删除了多余的页号按钮
        while(arr.length > 0) {
            var $item = arr.pop();
            $item.off("click", this["onClickHandler"]);
            $item.remove();
            isDel = true;
        }
        if(isDel) {
            var pageIdx = this.currPageIndex;
            if(pageIdx > this.pageTotals) pageIdx = this.pageTotals;
            this.selected(pageIdx);
        }
    } else {    //现有翻页按钮少于指定数量，则需要添加
        var offset = itemNum - nowItemCount;
        var lastItemPageIdx = parseInt($itemLast.text()); //最后一个页号按钮的页号
        var start = lastItemPageIdx + 1; //添加的起始页号
        var end = start + offset - 1;   //添加的结束页号
        if (end > pageTotals) { //添加的结束页号大于总页数
            end = pageTotals;
            start = end - offset + 1;
            for(var i = itemLastIdx, j = start - 1; i>= 0; i--, j--) {
                var $item = $(cs[i]);
                var cls = $item.attr("class");
                if (cls.indexOf("page_num") >= 0) {
                    $item.text(j);
                }
            }
        }
        for (; start <= end; start++) {
            var $item = $('<span class="page_num">' + start + '</span>');
            $item.on("click", null, this, this["onClickHandler"]);
            $itemLast.after($item);
            $itemLast = $item;
        }
        var pageIdx = this.currPageIndex;
        if(pageIdx > this.pageTotals) pageIdx = this.pageTotals;
        this.selected(pageIdx);
    }
};

/**
 * 选择指定页
 * @param pageIdx
 */
PageNav.prototype.selected = function(pageIdx) {
    var cs = this.navObj.children();
    var start = -1; //临时页号变量，从1开始
    if (pageIdx > this.currPageIndex) {
        //向后翻页
        if(this.rightSpace > 0) {
            var end = pageIdx + this.rightSpace;
            if (end > this.pageTotals) {
                end = this.pageTotals;
            }
            start = end - this.initItemNum + 1;
            if (start < 1) {
                start = 1;
            }
        }
    } else if (pageIdx < this.currPageIndex) {
        //向前翻页
        if(this.leftSpace > 0) {
            start = pageIdx - this.leftSpace;
            if (start < 1) {
                start = 1;
            }
            end = start + this.initItemNum - 1;
            if (end > this.pageTotals) {
                end = this.pageTotals;
            }
            start = end - this.initItemNum + 1;
            if (start < 1) {
                start = 1;
            }
        }
    }
    if(start > 0) {
        for(var i = 0; i < cs.length; i++) {
            var $item = $(cs[i]);
            var cls = $item.attr("class");
            if(cls.indexOf("page_num") >= 0) {
                $item.text(start);
                start++;
            }
        }
    }
    /**
     * 在items集合中查询class1和class2所指定的对象
     * @param items
     * @param class1
     * @param class2
     * @returns {{class1:对象, class2:对象}}
     */
    var query = function(items, class1, class2) {
        var obj = {};
        var count = 0;
        for(var i = 0; i < items.length; i++) {
            var $item = $(items[i]);
            var cls = $item.attr("class");
            if(cls == class1 || cls == class2) {
                obj[cls] = $item;
                count++;
            }
            if(count == 2) break;
        }
        return obj;
    };
    //此为根据页号选中某项
    for(var i = 0; i < cs.length; i++) {
        var $item = $(cs[i]);
        var cls = $item.attr("class");
        if(cls.indexOf("page_num") < 0) continue;
        var text = $item.text().trim();
        var v = parseInt(text);
        if(pageIdx == v) {
            if(this.$selectedItem) {
                this.$selectedItem.attr("class", "page_num");
            }
            $item.attr("class", "page_num_selected");
            this.$selectedItem = $item;
            this.currPageIndex = pageIdx;
            //以下确定不可用的按钮
            if(this.currPageIndex == this.pageTotals) {
                var obj = query(cs, "page_next", "page_last");
                var $next = obj["page_next"];
                var $last = obj["page_last"];
                if($next) $next.attr("class", "page_next_disabled");
                if($last) $last.attr("class", "page_last_disabled");
            } else {
                var obj = query(cs, "page_next_disabled", "page_last_disabled");
                var $next = obj["page_next_disabled"];
                var $last = obj["page_last_disabled"];
                if($next) $next.attr("class", "page_next");
                if($last) $last.attr("class", "page_last");
            }
            if(this.currPageIndex == 1) {
                var obj = query(cs, "page_first", "page_prev");
                var $first = obj["page_first"];
                var $prev = obj["page_prev"];
                if($first) $first.attr("class", "page_first_disabled");
                if($prev) $prev.attr("class", "page_prev_disabled");
            } else {
                var obj = query(cs, "page_first_disabled", "page_prev_disabled");
                var $first = obj["page_first_disabled"];
                var $prev = obj["page_prev_disabled"];
                if($first) $first.attr("class", "page_first");
                if($prev) $prev.attr("class", "page_prev");
            }
            break;
        }
    }
};

/**
 * 选择指定页，first、last、prev、next函数都会调用此函数，而此函数会调用回调函数或者当回调函数为空时直接调用selected函数
 * @param pageIndex
 */
PageNav.prototype.select = function(pageIndex) {
    if(pageIndex == this.currPageIndex) return;
    if(this.callback) {
        this.callback(pageIndex);
    } else {
        this.selected(pageIndex);
    }
};

/**
 * 首页
 */
PageNav.prototype.first = function() {
    if(this.currPageIndex < 0) return;
    if(this.currPageIndex <=1 ) return;
    var pageIndex = 1;
    this.select(pageIndex);
};

/**
 * 尾页
 */
PageNav.prototype.last = function() {
    if(this.currPageIndex < 0) return;
    if(this.currPageIndex >= this.pageTotals) return;
    var pageIndex = this.pageTotals;
    this.select(pageIndex);
};

/**
 * 上一页
 */
PageNav.prototype.prev = function() {
    if(this.currPageIndex < 0) return;
    if(this.currPageIndex <= 1) return;
    var pageIndex = this.currPageIndex - 1;
    this.select(pageIndex);
};

/**
 * 下一页
 */
PageNav.prototype.next = function() {
    if(this.currPageIndex < 0) return;
    if(this.currPageIndex >= this.pageTotals) return;
    var pageIndex = this.currPageIndex + 1;
    this.select(pageIndex);
};